稍微調整了一下程式,讓功能完整一點,然後再來調整。
既然最常更動的往往是頁面,那讓頁面的邏輯跟其他部分混在一起,就很容易互相影響而不好修改。所以通常在改善架構的第一小步,就是先把頁面的邏輯拆出來。
拆開的步驟很簡單,就是把「非」頁面邏輯的PHP程式碼,一步一步依照順序搬到程式開始的地方。
比較複雜的部份,是查詢的迴圈跟網頁的邏輯混在一起的地方。這些地方,需要把迴圈改成兩個,查詢的迴圈中,把資料放進陣列變數。然後在頁面呈現的迴圈中,每次處理陣列中的一列資料,這樣就可以拆開了。
除了拆出頁面的邏輯,這個時候也可以順便處理頁面重複的地方。例如頁首跟頁尾是共用的,所以可以拆到獨立的檔案中,然後再include進來。
原本的程式:(index.php)
<?php
session_start();
if(isset($_SESSION['user']['account'])) {
$member = true;
$name = $_SESSION['user']['name'];
} else $member = false;
$conn = mysql_connect('localhost', 'root', '');
if(!$conn)
die('mysql connection error.');
mysql_select_db('myforum');
if(isset($_SESSION['msg'])) {
$message = mysql_real_escape_string($_SESSION['msg']);
unset($_SESSION['msg']);
}
?>
<table width="800" border="1" cellpadding="0" cellspacing="0" align="center">
<!-- header start -->
<tr>
<th align="left">我的論壇</th>
</tr>
<tr>
<td style="text-align:right" bgcolor="#336699">
<table align="right">
<tr>
<?php
if($member) {
?>
<td>Welcome [<?php echo $name;?>] <button onclick='document.location.href="logout.php"'>登出</button></td>
<?php
} else {
?>
<form method="post" action="login.php">
<td>登入後可留言 </td>
<td>帳號</td>
<td><input type="text" name="account"></td>
<td>密碼</td><td><input type="password" name="password"></td>
<td><input type="submit" value="登入"></td>
</form>
<?php
}
?>
</tr>
</table>
</td>
</tr>
<!-- header end -->
<!-- content start-->
<tr height="600">
<td valign="top">
<table width="100%" border="1" cellspacing="0" cellpadding="5">
<tr bgcolor="#DDEEFF">
<th>論壇名稱</th>
<th>文章數</th>
<th>最新文章</th>
<th>操作</th>
</tr>
<?php
$sql = "SELECT f.*,count(a.forums_id) AS count FROM forums f LEFT JOIN articles a ON a.forums_id = f.id GROUP BY a.forums_id ORDER BY f.id";
$result = mysql_query($sql, $conn);
$count = 0;
while($row = mysql_fetch_array($result)) {
if($count%2==0) {
$style = 'bgcolor="#EEFFEE"';
} else {
$style = 'bgcolor="#FFFFFF"';
}
$sql = "SELECT * FROM articles WHERE forums_id=".$row['id']." ORDER BY id DESC LIMIT 1";
$result1 = mysql_query($sql, $conn);
$row1 = mysql_fetch_array($result1);
?>
<tr <?php echo $style;?>>
<td><?php echo $row['name'];?></td>
<td><?php echo $row['count'];?></td>
<td><?php echo $row1['title'];?></td>
<td>
<button onclick="document.location.href='forum.php?id=<?php echo $row['id'];?>'">進入</button>
</td>
</tr>
<?php
$count++;
}
?>
</table>
</td>
</tr>
<!-- content end -->
<!-- footer start -->
<tr bgcolor="#336699">
<td align="center">
<font color="#EFEFEF">Copyright 1899 by Fillano</font>
</td>
</tr>
<!-- footer end -->
</table>
<script>
<?php
if(isset($message)) {
?>
alert('<?php echo $message;?>');
<?php
}
?>
</script>
然後開始把邏輯拆開。這裡其實會動到的程式碼,主要在資料查詢這一塊:
<?php
$sql = "SELECT f.*,count(a.forums_id) AS count FROM forums f LEFT JOIN articles a ON a.forums_id = f.id GROUP BY a.forums_id ORDER BY f.id";
$result = mysql_query($sql, $conn);
$count = 0;
while($row = mysql_fetch_array($result)) {
if($count%2==0) {
$style = 'bgcolor="#EEFFEE"';
} else {
$style = 'bgcolor="#FFFFFF"';
}
$sql = "SELECT * FROM articles WHERE forums_id=".$row['id']." ORDER BY id DESC LIMIT 1";
$result1 = mysql_query($sql, $conn);
$row1 = mysql_fetch_array($result1);
?>
<tr <?php echo $style;?>>
<td><?php echo $row['name'];?></td>
<td><?php echo $row['count'];?></td>
<td><?php echo $row1['title'];?></td>
<td>
<button onclick="document.location.href='forum.php?id=<?php echo $row['id'];?>'">進入</button>
</td>
</tr>
<?php
$count++;
}
?>
先把資料查詢的迴圈跟頁面拆開,把資料存入一個陣列變數$data:
<?php
$sql = "SELECT f.*,count(a.forums_id) AS count FROM forums f LEFT JOIN articles a ON a.forums_id = f.id GROUP BY a.forums_id ORDER BY f.id";
$result = mysql_query($sql, $conn);
$count = 0;
$data = array();
while($row = mysql_fetch_array($result)) {
if($count%2==0) {
$style = 'bgcolor="#EEFFEE"';
} else {
$style = 'bgcolor="#FFFFFF"';
}
$sql = "SELECT * FROM articles WHERE forums_id=".$row['id']." ORDER BY id DESC LIMIT 1";
$result1 = mysql_query($sql, $conn);
$row1 = mysql_fetch_array($result1);
$data[] = array('id'=>$row['id'], 'name'=>$row['name'], 'count'=>$row['count'], 'title'=>$row1['title'], 'style'=>$style);
$count++;
}
?>
<tr <?php echo $style;?>>
<td><?php echo $row['name'];?></td>
<td><?php echo $row['count'];?></td>
<td><?php echo $row1['title'];?></td>
<td>
<button onclick="document.location.href='forum.php?id=<?php echo $row['id'];?>'">進入</button>
</td>
</tr>
<?php
?>
然後在頁面部分,改成對這個陣列變數用foreach來迭代:
<?php
$sql = "SELECT f.*,count(a.forums_id) AS count FROM forums f LEFT JOIN articles a ON a.forums_id = f.id GROUP BY a.forums_id ORDER BY f.id";
$result = mysql_query($sql, $conn);
$count = 0;
$data = array();
while($row = mysql_fetch_array($result)) {
if($count%2==0) {
$style = 'bgcolor="#EEFFEE"';
} else {
$style = 'bgcolor="#FFFFFF"';
}
$sql = "SELECT * FROM articles WHERE forums_id=".$row['id']." ORDER BY id DESC LIMIT 1";
$result1 = mysql_query($sql, $conn);
$row1 = mysql_fetch_array($result1);
$data[] = array('id'=>$row['id'], 'name'=>$row['name'], 'count'=>$row['count'], 'title'=>$row1['title'], 'style'=>$style);
$count++;
}
foreach($data as $row) {
?>
<tr <?php echo $row['style'];?>>
<td><?php echo $row['name'];?></td>
<td><?php echo $row['count'];?></td>
<td><?php echo $row['title'];?></td>
<td>
<button onclick="document.location.href='forum.php?id=<?php echo $row['id'];?>'">進入</button>
</td>
</tr>
<?php
}
?>
拆開以後,資料查詢的部份跟頁面已經沒有關係了,所以可以把它往前移,接近完工的程式就變成這樣:
<?php
session_start();
if(isset($_SESSION['user']['account'])) {
$member = true;
$name = $_SESSION['user']['name'];
} else $member = false;
$conn = mysql_connect('localhost', 'root', '');
if(!$conn)
die('mysql connection error.');
mysql_select_db('myforum');
if(isset($_SESSION['msg'])) {
$message = mysql_real_escape_string($_SESSION['msg']);
unset($_SESSION['msg']);
}
$sql = "SELECT f.*,count(a.forums_id) AS count FROM forums f LEFT JOIN articles a ON a.forums_id = f.id GROUP BY a.forums_id ORDER BY f.id";
$result = mysql_query($sql, $conn);
$count = 0;
$data = array();
while($row = mysql_fetch_array($result)) {
if($count%2==0) {
$style = 'bgcolor="#EEFFEE"';
} else {
$style = 'bgcolor="#FFFFFF"';
}
$sql = "SELECT * FROM articles WHERE forums_id=".$row['id']." ORDER BY id DESC LIMIT 1";
$result1 = mysql_query($sql, $conn);
$row1 = mysql_fetch_array($result1);
$data[] = array('id'=>$row['id'], 'name'=>$row['name'], 'count'=>$row['count'], 'title'=>$row1['title'], 'style'=>$style);
$count++;
}
?>
<table width="800" border="1" cellpadding="0" cellspacing="0" align="center">
<!-- header start -->
<tr>
<th align="left">我的論壇</th>
</tr>
<tr>
<td style="text-align:right" bgcolor="#336699">
<table align="right">
<tr>
<?php
if($member) {
?>
<td>Welcome [<?php echo $name;?>] <button onclick='document.location.href="logout.php"'>登出</button></td>
<?php
} else {
?>
<form method="post" action="login.php">
<td>登入後可留言 </td>
<td>帳號</td>
<td><input type="text" name="account"></td>
<td>密碼</td><td><input type="password" name="password"></td>
<td><input type="submit" value="登入"></td>
</form>
<?php
}
?>
</tr>
</table>
</td>
</tr>
<!-- header end -->
<!-- content start-->
<tr height="600">
<td valign="top">
<table width="100%" border="1" cellspacing="0" cellpadding="5">
<tr bgcolor="#DDEEFF">
<th>論壇名稱</th>
<th>文章數</th>
<th>最新文章</th>
<th>操作</th>
</tr>
<?php
foreach($data as $row) {
?>
<tr <?php echo $row['style'];?>>
<td><?php echo $row['name'];?></td>
<td><?php echo $row['count'];?></td>
<td><?php echo $row['title'];?></td>
<td>
<button onclick="document.location.href='forum.php?id=<?php echo $row['id'];?>'">進入</button>
</td>
</tr>
<?php
}
?>
</table>
</td>
</tr>
<!-- content end -->
<!-- footer start -->
<tr bgcolor="#336699">
<td align="center">
<font color="#EFEFEF">Copyright 1899 by Fillano</font>
</td>
</tr>
<!-- footer end -->
</table>
<script>
<?php
if(isset($message)) {
?>
alert('<?php echo $message;?>');
<?php
}
?>
</script>
可以看出,除了開頭這一段php之外,html中的php程式碼,都是在處理頁面的邏輯,資料都是倚賴php程式中產生的變數。試跑一下,程式沒有錯誤,然後就可以把php程式與html的部份進一步拆開成兩個檔案。為了管理方便,html部分就把它放到views目錄,然後再透過include引入。
完工的index.php:
<?php
session_start();
if(isset($_SESSION['user']['account'])) {
$member = true;
$name = $_SESSION['user']['name'];
} else $member = false;
$conn = mysql_connect('localhost', 'root', '');
if(!$conn)
die('mysql connection error.');
mysql_select_db('myforum');
if(isset($_SESSION['msg'])) {
$message = mysql_real_escape_string($_SESSION['msg']);
unset($_SESSION['msg']);
}
$sql = "SELECT f.*,count(a.forums_id) AS count FROM forums f LEFT JOIN articles a ON a.forums_id = f.id GROUP BY a.forums_id ORDER BY f.id";
$result = mysql_query($sql, $conn);
$count = 0;
$data = array();
while($row = mysql_fetch_array($result)) {
if($count%2==0) {
$style = 'bgcolor="#EEFFEE"';
} else {
$style = 'bgcolor="#FFFFFF"';
}
$sql = "SELECT * FROM articles WHERE forums_id=".$row['id']." ORDER BY id DESC LIMIT 1";
$result1 = mysql_query($sql, $conn);
$row1 = mysql_fetch_array($result1);
$data[] = array('id'=>$row['id'], 'name'=>$row['name'], 'count'=>$row['count'], 'title'=>$row1['title'], 'style'=>$style);
$count++;
}
include 'views/index.php';
?>
完工後的views/index.php:
<table width="800" border="1" cellpadding="0" cellspacing="0" align="center">
<!-- header start -->
<tr>
<th align="left">我的論壇</th>
</tr>
<tr>
<td style="text-align:right" bgcolor="#336699">
<table align="right">
<tr>
<?php
if($member) {
?>
<td>Welcome [<?php echo $name;?>] <button onclick='document.location.href="logout.php"'>登出</button></td>
<?php
} else {
?>
<form method="post" action="login.php">
<td>登入後可留言 </td>
<td>帳號</td>
<td><input type="text" name="account"></td>
<td>密碼</td><td><input type="password" name="password"></td>
<td><input type="submit" value="登入"></td>
</form>
<?php
}
?>
</tr>
</table>
</td>
</tr>
<!-- header end -->
<!-- content start-->
<tr height="600">
<td valign="top">
<table width="100%" border="1" cellspacing="0" cellpadding="5">
<tr bgcolor="#DDEEFF">
<th>論壇名稱</th>
<th>文章數</th>
<th>最新文章</th>
<th>操作</th>
</tr>
<?php
foreach($data as $row) {
?>
<tr <?php echo $row['style'];?>>
<td><?php echo $row['name'];?></td>
<td><?php echo $row['count'];?></td>
<td><?php echo $row['title'];?></td>
<td>
<button onclick="document.location.href='forum.php?id=<?php echo $row['id'];?>'">進入</button>
</td>
</tr>
<?php
}
?>
</table>
</td>
</tr>
<!-- content end -->
<!-- footer start -->
<tr bgcolor="#336699">
<td align="center">
<font color="#EFEFEF">Copyright 1899 by Fillano</font>
</td>
</tr>
<!-- footer end -->
</table>
<script>
<?php
if(isset($message)) {
?>
alert('<?php echo $message;?>');
<?php
}
?>
</script>
這樣要修改頁面時,只需要去改views/index.php,不用去改index.php了。另外,在修改views/index.php時,需要注意的就是使用的變數與邏輯是否跟之前一致,應該就可以正確執行。
======
在頁面更複雜以後,像這樣簡單的切割可能還不夠。早期最好的方案是使用smarty這個template engine,不過目前有更多好選擇,例如twig。明天就開始嘗試套用twig,並且把一些屬於頁面layout的部份與頁面內容的部份進一步拆開。